package com.zsck.zsgy.base

import android.os.Looper
import androidx.lifecycle.MutableLiveData
import com.zsck.commonbase.http.factory.ResultException
import com.zsck.zsgy.http.exception.ApiException
import com.zsck.zsgy.util.showToast
import com.zsck.zsgy.widget.LoadingDialog
import kotlinx.coroutines.*
import org.json.JSONException
import retrofit2.HttpException
import java.net.ConnectException
import java.net.SocketTimeoutException
import java.net.UnknownHostException

/**
 * typealias用于省略如泛型之类用不到的信息
 */
typealias Error = suspend (e: ApiException) -> Unit

/**
 * des :base数据层仓库
 *coroutineScope 注入viewModel的coroutineScope用于协程管理
 * errorLiveData 业务出错或者爆发异常，由errorLiveData通知视图层去处理
 */

open class BaseRepository(
    private val coroutineScope: CoroutineScope,
    val errorLiveData: MutableLiveData<ApiException>
) {
    private var mDialog: LoadingDialog? = null




    /**
     * 对协程进行封装,统一处理错误信息
     *
     * @param block   执行中
     * @param success 执行成功
     */
    protected fun <T> launch(
        block: suspend () -> T,
        success: suspend (T) -> Unit,
        error: Error? = null
    ): Job {
        return coroutineScope.launch {
            runCatching {
                withContext(Dispatchers.IO) {
                    block()
                }
            }.onSuccess {
                it?.let {
                    success(it)
                }

            }.onFailure {
                it.printStackTrace()
                if(it is ResultException){
                    showToast(it.errMsg)
                    getApiException(it).apply {
                        error?.invoke(this)
                        showToast(it.errMsg)
                        //统一响应错误信息
                        errorLiveData.value = this
                    }
                }else{
                    getApiException(it).apply {
                        error?.invoke(this)
                        showToast(errorMessage)
                        //统一响应错误信息
                        errorLiveData.value = this
                    }
                }

            }
        }
    }

    /**
     * 捕获异常信息
     */
    private fun getApiException(e: Throwable): ApiException {
        return when (e) {
            is UnknownHostException -> {
                ApiException("网络异常", "-100")
            }
            is JSONException -> {//|| e is JsonParseException
                ApiException("数据解析错误", "-100")
            }
            is SocketTimeoutException -> {
                ApiException("连接超时", "-100")
            }
            is ConnectException -> {
                ApiException("连接错误",  "-100")
            }
            is HttpException -> {
                ApiException("http code ${e.code()}",  "-100")
            }

            is ApiException -> {
                e
            }

            /**
             * 如果协程还在运行，个别机型退出当前界面时，viewModel会通过抛出CancellationException，
             * 强行结束协程，与java中InterruptException类似，所以不必理会,只需将toast隐藏即可
             */
            is CancellationException -> {
                ApiException("",  "-10")
            }
            else -> {
                ApiException("未知错误",  "-100")
            }
        }
    }
}